import re
from collections import defaultdict

from downloader import GeneRIF
import str_distances


class GeneRIFSearcher:
    """Class responsible for searching in generifs.

    Parameters:
    -----------
        fetcher : {class, GeneRIF}
    """
    def __init__(self, fetcher):
        self._search_funcs = {}
        self.register_search_func('simple', self._simple_search)
        self.register_search_func('regexp', self._regexp_search)
        self._fetcher = fetcher
        if self._fetcher._data == None:
            try:
                self._fetcher.load()
            except:
                self._fetcher.text_parse_generif()
        self._data = self._fetcher._data
        
    def register_search_func(self, name, func):
        if name in self._search_funcs:
            print "%s already registered as a search function!"
            return
        self._search_funcs[name] = func 
    
    def search(self, terms, type='simple', *args):
        if not type in self._search_funcs:
            raise ValueError("%s is not a registered search function.")
        return self._search_funcs[type](terms, *args)
    
    # Private interface
    def _simple_search(self, terms, *args):
        """ A simple is-present search over terms.

        Returns genes whos generifs containing the string(s)
        given in terms.
        """
        if isinstance(terms, str):
            terms = [terms]
        genes = defaultdict(list)
        for gene, rifs in self._data.items():
            for line in rifs:
                for word in terms:
                    if word.lower() in line.lower():
                        genes[gene].append(line)
        return genes
    
    def _regexp_search(self, patterns='*.dr.+Livingstone.*', *args):
        if isinstance(patterns, str):
            patterns = [patterns]
        genes = set()
        for gene, rifs in self._data.items():
            for pattern in patterns:
                patt = re.compile(pattern)
                for line in rifs:
                    mtch = re.findall(patt, line)
                    if len(mtch) > 0:
                        genes.add((gene, line))
        return list(genes)

    def _dist_search(self, terms, dfunc=None, cutoff=0):
        pass

    
